package com.gome.axwl.aoc.facade.util;

import com.alibaba.fastjson.JSONObject;
import com.gome.axwl.aoc.entity.zq.*;
import com.gome.commons.json.util.JsonUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * 调用众签接口工具类
 * Created by wanglongyu on 2018/7/17.
 */
@Service
public class ZQRequestUtil {
    @Value("${zqConfig.zqid}")
    private String ZQID;
    @Value("${zqConfig.private_key}")
    private String PRIVATE_KEY;
    @Value("${zqConfig.request_url}")
    private String REQUEST_URL;

    private Logger logger = LoggerFactory.getLogger("众签接口类");

    /***************众签接口名********************/
    /**创建合同模板接口*/
    private final String CREATE_TEMPLATE = "/createTemplate";
    /**下载合同模板接口*/
    private final String DOWNLOAD_TEMPLATE = "/getTemplateUrl";
    /**下载合同*/
    private final String DOWNLOAD_CONTRACT = "/getPdfUrl";
    /**下载合同详情图片*/
    private final String DOWNLOAD_CONTRACT_IMG = "/getImg";
    /**将合同模板与合同附件生成新模板*/
    private final String UPDATE_TEMPLATE = "/uploadTemplate";
    /**下载模板与合同生成附件后的空白合同模板图片*/
    private final String DOWNLOAD_EMPTY_CONTRACT_IMG = "/getTemplateImg";
    /**合同生效标记*/
    private final String COMPLITE_CONTRACT = "/completionContract";
    /**企业用户颁发数字证书*/
    private final String ENTP_REG = "/entpReg";
    /**个人用户颁发数字证书*/
    private final String PERSON_REG = "/personReg";
    /**个人用户更新数字证书*/
    private final String PERSON_UPDATE = "/personUpdate";
    /**骑缝章签署*/
    private final String SIGN_CHECK_MARK = "/signCheckMark";
    /**后台自动签署*/
    private final String SIGN_AUTO = "/signAuto";
    /**根据模板生成合同*/
    private final String CREATE_CONTRACT = "/pdfTemplate";

    static <T> T jsonStr2Bean(String jsonStr, Class<T> clazz) {
        return JsonUtil.toObject(jsonStr, clazz);
    }


    /*******************************************************/
    /***********************合同模板**************************/
    /*******************************************************/
    /***
     * 创建合同模板
     * @param contract 模板base64数据
     * @param t_name 模板名称
     * @return
     */
    public ZQContractTemplate createTemplate(String contract,String t_name){
        Map<String,String> map = new HashMap<String,String>();
        map.put("contract",contract);
        map.put("t_name",t_name);
        long start = System.currentTimeMillis();
        ZQContractTemplate response = ZQPost(CREATE_TEMPLATE,map,ZQContractTemplate.class);
        logger.info("[调用众签] [创建模板] 耗时: [ {}ms ] 参数: {} 返回结果: {}", System.currentTimeMillis() - start, JSONObject.toJSON(map), JSONObject.toJSON(response));
        return response;
    }

    /***
     * 下载合同模板
     * @param templateNo 模板编码
     * @return 返回模板地址
     */
    public ZQTemplatePdf downloadTemplate(String templateNo){
        Map<String,String> map = new HashMap<String,String>();
        map.put("t_no",templateNo);
        long start = System.currentTimeMillis();
        ZQTemplatePdf response = ZQPost(DOWNLOAD_TEMPLATE,map,ZQTemplatePdf.class);
        logger.info("[调用众签] [模板下载] 耗时: [ {}ms ] 参数: {} 返回结果: {}", System.currentTimeMillis() - start, JSONObject.toJSON(map), JSONObject.toJSON(response));
        return response;
    }

    /***
     * 根据模板和 合同附件创建新模板
     * @param contractFile 附件PDF信息
     * @param t_name 新模板名称
     * @param t_no 旧模板编码
     * @return
     */
    public ZQEmptyContract updateTemplate(String contractFile,String t_name,String t_no){
        Map<String,String> map = new HashMap<String,String>();
        map.put("contract",contractFile);
        map.put("t_no",t_no);
        map.put("t_name",t_name);
        long start = System.currentTimeMillis();
        ZQEmptyContract response = ZQPost(UPDATE_TEMPLATE,map,ZQEmptyContract.class);
        logger.info("[调用众签] [根据模板和 合同附件创建新模板] 耗时: [ {}ms ] 参数: {} 返回结果: {}", System.currentTimeMillis() - start, JSONObject.toJSON(map), JSONObject.toJSON(response));
        return response;
    }

    /***
     * 下载模板与附件生成的新模板 图片
     * @param t_no 模板编码
     * @return 图片地址列表
     */
    public ZQContractImage downloadEmptyContractImg(String t_no){
        Map<String,String> map = new HashMap<String,String>();
        map.put("t_no",t_no);
        long start = System.currentTimeMillis();
        ZQContractImage response = ZQPost(DOWNLOAD_EMPTY_CONTRACT_IMG,map,ZQContractImage.class);
        logger.info("[调用众签] [下载模板与附件生成的新模板] 耗时: [ {}ms ] 参数: {} 返回结果: {}", System.currentTimeMillis() - start, JSONObject.toJSON(map), JSONObject.toJSON(response));
        return response;
    }
    /*******************************************************/
    /*************************合同***************************/
    /*******************************************************/

    /***
     * 下载合同PDF文件
     * @param contractNo 合同编码
     * @return 返回文件地址链接
     */
    public ZQContractPdf downloadContract(String contractNo){
        Map<String,String> map = new HashMap<String,String>();
        map.put("no",contractNo);
        long start = System.currentTimeMillis();
        ZQContractPdf response = ZQPost(DOWNLOAD_CONTRACT,map,ZQContractPdf.class);
        logger.info("[调用众签] [下载合同] 耗时: [ {}ms ] 参数: {} 返回结果: {}", System.currentTimeMillis() - start, JSONObject.toJSON(map), JSONObject.toJSON(response));
        return response;
    }

    /***
     * 下载合同详情图片
     * @param contractNo
     * @return 返回详情图片链接
     */
    public ZQContractImage downloadContractImg(String contractNo){
        Map<String,String> map = new HashMap<String,String>();
        map.put("no",contractNo);
        long start = System.currentTimeMillis();
        ZQContractImage response = ZQPost(DOWNLOAD_CONTRACT_IMG,map,ZQContractImage.class);
        logger.info("[调用众签] [下载合同详情] 耗时: [ {}ms ] 参数: {} 返回结果: {}", System.currentTimeMillis() - start, JSONObject.toJSON(map), JSONObject.toJSON(response));
        return response;
    }

    /***
     *  合同生效标记(必调接口)
     *  商户已完成所有用户的合同签署，调用该接口进行合同生效状态标记，同时后台将该合同进行存证。
     *  注：请在合同签署完成后调用此接口，该操作一旦完成将无法回退，且标记为生效的合同无法进行撤回或继续签署。
     * @param contractNo
     * @return
     */
    public ZQBaseResult completionContract(String contractNo){
        Map<String,String> map = new HashMap<String,String>();
        map.put("no",contractNo);
        long start = System.currentTimeMillis();
        ZQBaseResult response = ZQPost(COMPLITE_CONTRACT,map,ZQBaseResult.class);
        logger.info("[调用众签] [合同生效标记] 耗时: [ {}ms ] 参数: {} 返回结果: {}", System.currentTimeMillis() - start, JSONObject.toJSON(map), JSONObject.toJSON(response));
        return response;
    }
    /*******************************************************/
    /***********************证书签章**************************/
    /*******************************************************/
    /***
     * 企业用户颁发数字证书
     * @param userCode 用户ID
     * @param name 企业名称
     * @param certificate 企业机构代码
     * @param address 企业注册地址
     * @param contact 企业联系人
     * @param mobile 联系人电话
     * @return
     */
    public ZQBaseResult entpReg(String userCode, String name,String certificate,String address,String contact,String mobile){
        Map<String,String> map = new HashMap<String,String>();
        map.put("user_code", userCode);//用户唯一标示，该值不能重复
        map.put("name", name);//企业名称
        map.put("certificate", certificate);//营业执照号或社会统一代码
        map.put("address", address); //企业注册地址
        map.put("contact", contact);//联系人
        map.put("mobile", mobile);//联系电话（手机号码）
        long start = System.currentTimeMillis();
        ZQBaseResult response = ZQPost(ENTP_REG,map,ZQBaseResult.class);
        logger.info("[调用众签] [企业用户颁发数字证书] 耗时: [ {}ms ] 参数: {} 返回结果: {}", System.currentTimeMillis() - start, JSONObject.toJSON(map), JSONObject.toJSON(response));
        return response;
    }

    /***
     * 个人用户颁发数字证书
     * @param userCode 用户ID
     * @param name 姓名
     * @param id_card_no  身份证号
     * @param mobile 电话
     * @return
     */
    public ZQBaseResult personReg(String userCode, String name,String id_card_no,String mobile){
        Map<String,String> map = new HashMap<String,String>();
        map.put("user_code", userCode);//用户唯一标示，该值不能重复
        map.put("name", name);//用户名称
        map.put("id_card_no", id_card_no);//身份证号
        map.put("mobile", mobile);//联系电话（手机号码）
        long start = System.currentTimeMillis();
        ZQBaseResult response = ZQPost(PERSON_REG,map,ZQBaseResult.class);
        logger.info("[调用众签] [个人用户颁发数字证书] 耗时: [ {}ms ] 参数: {} 返回结果: {}", System.currentTimeMillis() - start, JSONObject.toJSON(map), JSONObject.toJSON(response));
        return response;
    }
    /***
     * 个人用户更新数字证书
     * @param userCode 用户ID
     * @param name 姓名
     * @param id_card_no  身份证号
     * @param mobile 电话
     * @return
     */
    public ZQBaseResult personUpdate(String userCode, String name,String id_card_no,String mobile){
        Map<String,String> map = new HashMap<String,String>();
        map.put("user_code", userCode);//用户唯一标示，该值不能重复
        map.put("name", name);//用户名称
        map.put("id_card_no", id_card_no);//身份证号
        map.put("mobile", mobile);//联系电话（手机号码）
        long start = System.currentTimeMillis();
        ZQBaseResult response = ZQPost(PERSON_UPDATE,map,ZQBaseResult.class);
        logger.info("[调用众签] [个人用户更新数字证书] 耗时: [ {}ms ] 参数: {} 返回结果: {}", System.currentTimeMillis() - start, JSONObject.toJSON(map), JSONObject.toJSON(response));
        return response;
    }

    /***
     * 骑缝章签署
     * @param no 合同编码
     * @param signers 当前合同需要签署的用户ID列表
     * @return
     */
    public ZQBaseResult signCheckMark(String no, String signers){
        Map<String,String> map = new HashMap<String,String>();
        map.put("no", no);//合同编码
        map.put("signers", signers);//当前合同需要签署的用户ID列表
        long start = System.currentTimeMillis();
        ZQBaseResult response = ZQPost(SIGN_CHECK_MARK,map,ZQBaseResult.class);
        logger.info("[调用众签] [骑缝章签署] 耗时: [ {}ms ] 参数: {} 返回结果: {}", System.currentTimeMillis() - start, JSONObject.toJSON(map), JSONObject.toJSON(response));
        return response;
    }

    /***
     * 后台自动签署
     * @param no 合同编码
     * @param signers 当前合同需要签署的用户ID列表
     * @return
     */
    public ZQBaseResult signAuto(String no, String signers){
        Map<String,String> map = new HashMap<String,String>();
        map.put("no", no);//合同编码
        map.put("signers", signers);//当前合同需要签署的用户ID列表
        long start = System.currentTimeMillis();
        ZQBaseResult response = ZQPost(SIGN_AUTO,map,ZQBaseResult.class);
        logger.info("[调用众签] [后台自动签署] 耗时: [ {}ms ] 参数: {} 返回结果: {}", System.currentTimeMillis() - start, JSONObject.toJSON(map), JSONObject.toJSON(response));
        return response;
    }

    /***
     * 根据模板生成合同
     * @param contractNo  自定义合同编码
     * @param contractName 自定义合同名称
     * @param templateNo 模板编码
     * @param contractVal 填写好的模板json
     * @return
     */
    public ZQBaseResult createContract(String contractNo, String contractName,String templateNo,String contractVal){
        Map<String,String> map = new HashMap<String,String>();
        map.put("no", contractNo);
        map.put("name", contractName);
        map.put("t_no", templateNo);
        map.put("contract_val", contractVal);
        long start = System.currentTimeMillis();
        ZQBaseResult response = ZQPost(SIGN_AUTO,map,ZQBaseResult.class);
        logger.info("[调用众签] [后台自动签署] 耗时: [ {}ms ] 参数: {} 返回结果: {}", System.currentTimeMillis() - start, JSONObject.toJSON(map), JSONObject.toJSON(response));
        return response;
    }




    /***
     * 公共调用众签方法
     * @param url 接口名
     * @param map 封装好参数的map
     * @param clazz 返回类型
     * @param <T>
     * @return
     */
    private <T> T ZQPost(String url, Map<String, String> map, Class<T> clazz){
        EncryptData ed = new EncryptData();
        map.put("zqid",ZQID);
        String sign_val = ed.encrptData(map,PRIVATE_KEY);//对请求进行签名加密
        map.put("sign_val", sign_val);//添加签名值
        String requestUrl = REQUEST_URL + url;
        String response = "";
        try {
            response = HttpRequest.sendPost(requestUrl, map);//向服务端发送请求，并接收请求结果
        } catch (IOException e) {
            logger.info("调用众签失败[ {} ]",e.getMessage());
        }
        return jsonStr2Bean(response,clazz);
    }

}
